package com.lin.manager.file.oss;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.lin.manager.common.ex.BizException;
import com.lin.manager.file.entity.FileConfigEntity;
import com.lin.manager.file.model.vo.FileVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

/**
 * @作者: 林江
 * @创建时间: 2024/3/22
 * @功能: 云服务上传接口
 */
@Slf4j
public class AlibabaOssServiceImpl extends AbstractOssService {
    private OssService delegate;
    private final static String NAME = "alibaba";

    public AlibabaOssServiceImpl() {
        super(NAME);
    }

    @Override
    public void doUpload(MultipartFile file, FileConfigEntity fileConfig, Map<String, Object> resp) throws Exception {
        if (isSupport(fileConfig.getPlatform())) {
            // 本地文件上传
            log.info("阿里云对象存储上传。。。。。。。。。。。。");
            OSS ossClient = createOssClient(fileConfig);
            try (InputStream inputStream = file.getInputStream()) {
                String fileName = file.getOriginalFilename();
                String suffix = FilenameUtils.getExtension(fileName);
                String newFilename = (new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "/" + UUID.randomUUID().toString() + "." + suffix);
                // 创建PutObjectRequest对象。
                PutObjectRequest putObjectRequest = new PutObjectRequest(fileConfig.getBucket(), newFilename, inputStream);
                // 发送上传请求
                ossClient.putObject(putObjectRequest);

                // 可以使用凭证生成临时的url
                URL url = ossClient.generatePresignedUrl(fileConfig.getBucket(), newFilename, new Date());
                String fullpath = url.toString().substring(0, url.toString().indexOf("?"));

                // 封装数据
                resp.put(fileConfig.getCode(), createFileVo(fullpath, newFilename, fileName));
            } catch (OSSException oe) {
                log.error("上传文件到阿里云oss异常{},Code:{}", oe.getErrorCode(), oe.getErrorCode());
                throw new BizException(String.format("上传文件到阿里云oss异常[%s],Code:[%s]", oe.getErrorCode(), oe.getErrorCode()));
            } catch (ClientException ce) {
                log.error("阿里云对象连接网络异常。。。。。。。。。。。。。。。。。。。。");
                throw new BizException(String.format("阿里云对象连接网络异常:[%s]", ce.getMessage()));
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
        delegate.doUpload(file, fileConfig, resp);
    }

    @Override
    public void doDownload(HttpServletResponse response, FileVo fileVo, FileConfigEntity fileConfig) throws Exception {
        if (isSupport(fileConfig.getPlatform())) {
            log.info("阿里云对象存储下载。。。。。。。。。。。。");
            OSS ossClient = createOssClient(fileConfig);
            try {
                // 创建GetObjectRequest对象。
                GetObjectRequest getObjectRequest = new GetObjectRequest(fileConfig.getBucket(), fileVo.getPath());
                // ossObject包含文件所在的存储空间名称、文件名称、文件元数据以及一个输入流。
                OSSObject ossObject = ossClient.getObject(getObjectRequest);

                // 读取文件内容。
                byte[] bytes = IOUtils.toByteArray(ossObject.getObjectContent());

                ossObject.close();
                write(response, fileVo.getName(), bytes);
                return;
            } catch (OSSException oe) {
                log.error("阿里云oss下载文件异常{},Code:{}", oe.getErrorCode(), oe.getErrorCode());
                throw new BizException("阿里云oss下载文件异常:" + oe.getErrorCode());
            } catch (ClientException ce) {
                log.error("阿里云对象连接网络异常。。。。。。。。。。。。。。。。。。。。");
                throw new BizException("连接阿里云oss，网络异常");
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
        delegate.doDownload(response, fileVo, fileConfig);
    }

    @Override
    public void next(OssService delegate) {
        this.delegate = delegate;
    }

    /**
     * 创建OSSClient实例。
     *
     * @param fileConfig
     * @return
     */
    private static OSS createOssClient(FileConfigEntity fileConfig) {
        OSS ossClient = new OSSClientBuilder().build(fileConfig.getOssUrl(), fileConfig.getOssAccessKeyId(), fileConfig.getOssAccessKeySecret());
        return ossClient;
    }
}
